package com.xjscrm.server.service.soptask.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.uzai.mobile.collect.api.dto.MicaTransDto;
import com.uzai.mobile.collect.api.dto.msg.MicaFriendTalkMsg;
import com.uzai.mobile.collect.api.dto.trigger.talk.MicaTalkContentTextMsg;
import com.uzai.mobile.collect.api.enums.MicaTalkMsgType;
import com.uzai.trace.TraceGenerate;
import com.xjscrm.common.annotation.MerId;
import com.xjscrm.common.entity.SopJob;
import com.xjscrm.common.entity.WwDevice;
import com.xjscrm.common.utils.DateUtil;
import com.xjscrm.common.utils.Tools;
import com.xjscrm.server.biz.RatelimitService;
import com.xjscrm.server.common.util.DeviceTools;
import com.xjscrm.server.dto.sopjob.SopJobQuery;
import com.xjscrm.server.enums.LimitRedisCacheKeyEnum;
import com.xjscrm.server.mapper.SopJobMapper;
import com.xjscrm.server.mapper.SopTaskMapper;
import com.xjscrm.server.mapper.WwDeviceMapper;
import com.xjscrm.server.service.soptask.*;
import com.xjscrm.server.vo.device.Device;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * SopJob阶段任务处理
 *
 * @author makejava
 * @since 2024-03-01 17:01:12
 */
@Slf4j
@Service
public class SopJobSyncServiceImpl implements SopJobSyncService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SopTaskMapper sopTaskMapper;
    @Autowired
    private RatelimitService ratelimitService;
    @Autowired
    private SopJobHanderService sopJobHanderService;
    @Autowired
    private SopJobMapper sopJobMapper;
    @Autowired
    private WwDeviceMapper wwDeviceMapper;
    @Autowired
    private SopJobNewCustomerService sopJobNewCustomerService;
    @Autowired
    private SopJobTagService sopJobTagService;
    @Autowired
    private SopJobGroupService sopJobGroupService;


    /**
     * 处理手动SOP任务
     *
     * @param merId
     * @return null
     * @author jitwxs
     * @date 2024/3/8 17:12
     */
    @Async("taskExecutorForXxJob")
    public void autoSopJobSyncByStep(@MerId Long merId) {

        try {
            log.info("--监控系统日志--开始--");

            //限流key
            String taskLimitKet = "-autoSopJobSyncByStep-taskLimitKey-merId=" + merId;
            Object object = redisTemplate.opsForValue().get(taskLimitKet);
            if (object != null) {
                return;
            }
            //保存限流key
            redisTemplate.opsForValue().set(taskLimitKet, taskLimitKet, 100, TimeUnit.SECONDS);

            log.info("-----处理SOPjob的阶段性消息----merId=" + merId);

            try {
                //查询当前所有开启的自动发圈的配置方案
                int now = DateUtil.getTime();

                SopJobQuery sopJobQuery = new SopJobQuery();
                sopJobQuery.setMerId(merId);
                sopJobQuery.setStatus(1);                   //进行中
                sopJobQuery.setStartSendTimeEnd(now + 30);  //提前30秒处理sopjob任务

                //查询所有的自动发圈配置记录
                Page<SopJob> page = new Page<>();
                page.setCurrent(1);//只查第一页
                page.setSize(10); //每页查询10个
                page.addOrder(OrderItem.asc("id"));//默认id升序
                Long idStart = 0L;
                List<SopJob> sopJobList = sopJobMapper.findByList(page, sopJobQuery);
                while (sopJobList != null && sopJobList.size() > 0) {
                    for (SopJob sopJob : sopJobList) {
                        if (sopJob.getId().longValue() >idStart.longValue()) {
                            idStart = sopJob.getId();
                        }

                        //限流判断
                        String rateLimitKey = "autoSopJobSyncByStep-jobId=" + sopJob.getId();
                        Object rateLimitKeyobject = redisTemplate.opsForValue().get(rateLimitKey);
                        if (rateLimitKeyobject == null) {
                            //保存限流key
                            redisTemplate.opsForValue().set(rateLimitKey, rateLimitKey, 300, TimeUnit.SECONDS);
                        } else {
                            continue;
                        }

                        try {

                            //进行中
                            if (Tools.getInteger(sopJob.getStatus()).intValue() == 1) {
                                //类型(1-手动sop;2-新客户sop;3-标签sop;4-群sop)
                                Integer type = Tools.getInteger(sopJob.getType());
                                if (type.intValue() == 1) {//手动sop任务
                                    sopJobHanderService.autoStepSopJobByHander(sopJob);
                                } else if (type.intValue() == 2) { //新客户sop
                                    sopJobNewCustomerService.autoStepSopJobByNewCustomer(sopJob);
                                } else if (type.intValue() == 3) { //标签sop
                                    sopJobTagService.autoStepSopJobByTag(sopJob);
                                } else if (type.intValue() == 4) { //群sop
                                    sopJobGroupService.autoStepSopJobByGroup(sopJob);
                                }
                            }
                        } catch (Exception e) {
                            log.error(e.getMessage(), e);
                        } finally {
                            //保存成功之后，手动删除限流redisKey
                            redisTemplate.delete(rateLimitKey);
                        }
                    }
                    sopJobQuery.setIdStart(idStart);
                    sopJobList = sopJobMapper.findByList(page, sopJobQuery);
                }
            } catch (Exception e) {
                log.info(e.getMessage(), e);
            } finally {
                //删除限流key
                redisTemplate.delete(taskLimitKet);
            }

        }catch (Exception e){
            log.error(e.getMessage() , e);
        }finally {
            log.info("--监控系统日志--结束--");
        }
    }


    /**
     * 处理是否是退订消息
     *
     * @param micaTransDto
     * @return null
     * @author jitwxs
     * @date 2024/3/8 17:12
     */
    @Async("taskExecutorForEvent")
    @TraceGenerate //注入消息id标签
    public void handerUnsubscribeMsg(MicaTransDto micaTransDto) {
        try {
            log.info("--监控系统日志--开始--");

            MicaFriendTalkMsg micaFriendTalkMsg = JSONObject.parseObject(micaTransDto.getData().toString(), MicaFriendTalkMsg.class);

            //只处理私聊消息，群聊不支持消息退订
            if (micaFriendTalkMsg.getGroup()) {
                return;
            }

            if (StringUtils.isBlank(micaTransDto.getDeviceId())) {
                return;
            }

            //查询该机器人的配置方案
            WwDevice wwDevice = wwDeviceMapper.queryByDeviceId(micaTransDto.getDeviceId(), micaTransDto.getMerId());
            if (wwDevice == null) {
                return;
            }
            Device device = DeviceTools.transDevice(wwDevice);
            if (device == null) {
                return;
            }

            //只支持文本消息
            if (micaFriendTalkMsg.getMsgType().intValue() != MicaTalkMsgType.TEXT.getCode().intValue()) {
                return;
            }

            //聊天消息
            MicaTalkContentTextMsg textContent = micaFriendTalkMsg.getTextContent();
            if (textContent == null) {
                return;
            }
            String msg = textContent.getText(); //聊天信息

            if (StringUtils.isBlank(msg)) {
                return;
            }

            //获取退订话术缓存key
            String unsubscribeKey = String.format(LimitRedisCacheKeyEnum.SOP_JOB_UNSUBSCRIBE_KEYWORD.getKey(), micaTransDto.getMerId(), device.getDeviceId(), micaFriendTalkMsg.getSendWxId(), msg);
            Object object = redisTemplate.opsForValue().get(unsubscribeKey);
            if (object != null) {
                try {
                    Long sopJobId = (Long) object;
                    if (sopJobId != null) {
                        SopJob sopJob = sopJobMapper.selectById(sopJobId);
                        if (sopJob != null) {
                            sopJob.setStatus(3); //用户退订
                            sopJob.setUpdateTime(DateUtil.getTime());
                            sopJobMapper.updateStatusById(sopJob);
                        }
                    }
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                }
            }

        }catch (Exception e){
            log.error(e.getMessage(), e);
        }finally {
            log.info("--监控系统日志--结束--");
        }
    }

}
